using System;
using System.Collections;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
/*
* 源码已托管：https://gitee.com/dlgcy/WPFTemplateLib
* 版本：2024年8月20日
*/
namespace WPFTemplateLib.Attached
{
	/// <summary>
	/// TabControl 附加属性帮助类
	/// </summary>
	public class TabControlAttached
	{
		#region TabControl 绑定模式下，让每一个标签页有自己单独的界面实例

		//https://stackoverflow.com/questions/43347266/wpf-tabcontrol-create-only-one-view-at-all-tabs

		#region [附加属性] 每一项能创建单独界面实例的 ItemsSource
		public static IList GetCachedItemsSource(DependencyObject obj)
		{
			return (IList)obj.GetValue(CachedItemsSourceProperty);
		}
		/// <summary>
		/// 每一项能创建单独界面实例的 ItemsSource
		/// </summary>
		public static void SetCachedItemsSource(DependencyObject obj, IList value)
		{
			obj.SetValue(CachedItemsSourceProperty, value);
		}
		/// <summary>
		/// [附加属性] 每一项能创建单独界面实例的 ItemsSource
		/// </summary>
		public static readonly DependencyProperty CachedItemsSourceProperty =
			DependencyProperty.RegisterAttached("CachedItemsSource", typeof(IList), typeof(TabControlAttached), new PropertyMetadata(null, CachedItemsSource_Changed));
		#endregion

		#region [附加属性] ContentTemplate 中指定的界面元素的类型
		public static Type GetContentTemplateType(DependencyObject obj)
		{
			return (Type)obj.GetValue(ContentTemplateTypeProperty);
		}
		/// <summary>
		/// ContentTemplate 中指定的界面元素的类型
		/// </summary>
		public static void SetContentTemplateType(DependencyObject obj, Type value)
		{
			obj.SetValue(ContentTemplateTypeProperty, value);
		}
		/// <summary>
		/// [附加属性] ContentTemplate 中指定的界面元素的类型
		/// </summary>
		public static readonly DependencyProperty ContentTemplateTypeProperty =
			DependencyProperty.RegisterAttached("ContentTemplateType", typeof(Type), typeof(TabControlAttached), new PropertyMetadata(null, CachedItemsSource_Changed));
		#endregion

		#region [附加属性] ItemTemplate
		public static DataTemplate GetItemTemplate(DependencyObject obj)
		{
			return (DataTemplate)obj.GetValue(ItemTemplateProperty);
		}
		/// <summary>
		/// ItemTemplate
		/// </summary>
		public static void SetItemTemplate(DependencyObject obj, DataTemplate value)
		{
			obj.SetValue(ItemTemplateProperty, value);
		}
		/// <summary>
		/// [附加属性] ItemTemplate
		/// </summary>
		public static readonly DependencyProperty ItemTemplateProperty =
			DependencyProperty.RegisterAttached("ItemTemplate", typeof(DataTemplate), typeof(TabControlAttached), new PropertyMetadata(null, CachedItemsSource_Changed));
		#endregion

		/// <summary>
		/// CachedItemsSource 及相关的附加属性改变事件
		/// </summary>
		public static void CachedItemsSource_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
		{
			TabControl control = dependencyObject as TabControl;
			if(control == null)
				return;

			var changeAction = new NotifyCollectionChangedEventHandler((o, args) =>
			{
				if(dependencyObject is TabControl tabControl && GetContentTemplateType(tabControl) != null && GetCachedItemsSource(tabControl) != null)
					UpdateTabItems(tabControl);
			});

			// if the bound property is an ObservableCollection, attach change events
			if(e.OldValue is INotifyCollectionChanged oldValue)
				oldValue.CollectionChanged -= changeAction;

			if(e.NewValue is INotifyCollectionChanged newValue)
				newValue.CollectionChanged += changeAction;

			if(GetContentTemplateType(dependencyObject) != null && GetCachedItemsSource(control) != null)
				UpdateTabItems(control);
		}

		/// <summary>
		/// 更新 TabItems
		/// </summary>
		/// <param name="tabControl"></param>
		private static void UpdateTabItems(TabControl tabControl)
		{
			if(tabControl == null)
				return;

			IList itemsSource = GetCachedItemsSource(tabControl);
			if(itemsSource == null || itemsSource.Count == 0)
			{
				if(tabControl.Items.Count > 0)
					tabControl.Items.Clear();

				return;
			}

			// loop through items source and make sure datacontext is correct for each one
			for(int i = 0; i < itemsSource.Count; i++)
			{
				//新增的标签页;
				if(i >= tabControl.Items.Count)
				{
					TabItem tabItem = new TabItem
					{
						DataContext = itemsSource[i],
						Content = Activator.CreateInstance(GetContentTemplateType(tabControl)),
					};

					SetTabItemHeader(tabControl, tabItem);

					tabControl.Items.Add(tabItem);
					continue;
				}

				TabItem current = tabControl.Items[i] as TabItem;
				if(current == null)
					continue;

				if(current.DataContext != itemsSource[i])
				{
					current.DataContext = itemsSource[i];
				}

				SetTabItemHeader(tabControl, current);
			}

			//移除多余的标签页
			for(int i = tabControl.Items.Count; i > itemsSource.Count; i--)
			{
				tabControl.Items.RemoveAt(i - 1);
			}
		}

		/// <summary>
		/// 设置 TabItem 的 Header
		/// </summary>
		/// <param name="tabControl"></param>
		/// <param name="tabItem"></param>
		private static void SetTabItemHeader(TabControl tabControl, TabItem tabItem)
		{
			try
			{
				//使用设置的 ItemTemplate 载入 Header
				DataTemplate itemTemplate = GetItemTemplate(tabControl);
				if(itemTemplate == null)
				{
					//如果未设置 ItemTemplate 附加属性，则尝试使用原生的 ItemTemplate（这种情况可能会有 Xaml 绑定失败提示，不过不影响功能）
					itemTemplate = tabControl.ItemTemplate;
				}

				if(itemTemplate != null)
				{
					tabItem.Header = itemTemplate.LoadContent();
				}
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex);
			}
		}

		#endregion
	}
}
